package com.ran.servers.server;

import com.google.protobuf.Any;
import com.ran.delegate.MessageQueue;
import com.ran.entity.POJO.ClientChannel;
import com.ran.entity.POJO.Data;
import com.ran.servers.protobuf.SocketGameProtocol;
import com.ran.servers.protobuf.SocketGameProtocol.MainPack;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;
import java.util.HashMap;


/**
 * Title:  NettyServerHandler
 * Description: 服务端业务逻辑
 * Version:1.0.0
 * author ran
 * date 2024/5/08 10:00
 */
@Service("nettyServerHandler")
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    private final static Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    public static HashMap<String, ClientChannel> tcpChannelMap = new HashMap<>(10);
    /**
     * 空闲次数
     */
    private int idle_count = 1;
    /**
     * 发送次数
     */
    private int count = 1;

    /**
     * 建立连接时，发送一条消息
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        String address = inetSocketAddress.getAddress().getHostAddress()+":"+inetSocketAddress.getPort();
		ClientChannel clientChannel = new ClientChannel(address, 1, 1, ctx.channel());
		tcpChannelMap.put(address,clientChannel);
		System.out.println("客户端" + address + "已连接");
        super.channelActive(ctx);
    }

    /**
     * 超时处理 如果5秒没有接受客户端的心跳，就触发; 如果超过两次，则直接关闭;
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
        if (obj instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) obj;
            InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
            String address = inetSocketAddress.getAddress().getHostAddress()+":"+inetSocketAddress.getPort();
            if (IdleState.READER_IDLE.equals(event.state())) { // 如果读通道处于空闲状态，说明没有接收到心跳命令
                System.out.println("已经10秒没有接收到客户端的信息了");
                if(tcpChannelMap.containsKey(address)){
                    tcpChannelMap.get(address).setIdle_count(tcpChannelMap.get(address).getIdle_count()+1);
                }
                if (tcpChannelMap.get(address).getIdle_count() > 10) {
                    System.out.println("关闭这个不活跃的channel");
                    ctx.channel().close();
                }
            } else {
                tcpChannelMap.get(address).setIdle_count(1);
            }
        } else {
            super.userEventTriggered(ctx, obj);
        }
    }

    /**
     * 业务逻辑处理
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("第" + count + "次" + ",服务端接受的消息:" + msg);
        try {
            // 如果是protobuf类型的数据
            if (msg instanceof MainPack) {
                MainPack pack = (MainPack) msg;
                if (pack.getRequestCode() == SocketGameProtocol.RequestCode.State) {
                    System.out.println("接受到客户端:"+ctx.channel().remoteAddress()+"发送的心跳!");
                }else {
                    MessageQueue.messageQueue.put(new Data());
                }
            } else {
                System.out.println("未知数据!" + msg);
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ReferenceCountUtil.release(msg);
        }
        count++;
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error(cause.toString());
        ctx.close();
    }
}
